#include "postprocess.h"
#include <string>

PostProcess::PostProcess(int widgetWidth, int widgetHeight) : m_properties(0.3, 4.0, 2.4, 60, slotsdata::BloomProperties(12, 0.3, 2.0))
{
	m_hblurShader= new glutil::ShaderProgram();
	m_hblurShader->attachShaderFromFile(GL_VERTEX_SHADER, "data/main.vert");
	m_hblurShader->attachShaderFromFile(GL_FRAGMENT_SHADER, "data/hblur.frag");
	m_hblurShader->link();

	m_hblurShader->setUniform1i("mainTexture",0);
	m_hblurShader->setUniform2f("dispV",1.0,0.0);

	m_vblurShader= new glutil::ShaderProgram();
	m_vblurShader->attachShaderFromFile(GL_VERTEX_SHADER, "data/main.vert");
	m_vblurShader->attachShaderFromFile(GL_FRAGMENT_SHADER, "data/hblur.frag");
	m_vblurShader->link();

	m_vblurShader->setUniform1i("mainTexture",0);
	m_vblurShader->setUniform2f("dispV",0.0,1.0);

	m_raysShader = new glutil::ShaderProgram();
	m_raysShader->attachShaderFromFile(GL_VERTEX_SHADER, "data/main.vert");
	m_raysShader->attachShaderFromFile(GL_FRAGMENT_SHADER, "data/rays.frag");
	m_raysShader->link();
	m_raysShader->setUniform1i("mainTexture",0);

	m_finalShader = new glutil::ShaderProgram();
	m_finalShader->attachShaderFromFile(GL_VERTEX_SHADER, "data/main.vert");
	m_finalShader->attachShaderFromFile(GL_FRAGMENT_SHADER, "data/main.frag");
	m_finalShader->link();

	m_finalShader->setUniform1i("mainTexture",0);
	m_finalShader->setUniform1i("blurTexture",1);
	m_finalShader->setUniform1i("raysTexture",2);
	m_finalShader->setUniform1i("bloomLevels",4);

	widgetResized(widgetWidth, widgetHeight);

	m_hblurPass= new glutil::EffectsPass1to1(m_hblurShader, &m_mainFBO,&m_hblurFBO);
	m_vblurPass= new glutil::EffectsPass1to1(m_vblurShader, &m_hblurFBO,&m_vblurFBO);
	m_raysPass = new glutil::EffectsPass1to1(m_raysShader, &m_mainFBO, &m_hblurFBO);

	m_finalPass = new glutil::EffectsPass(m_finalShader, NULL);
	m_finalPass->setTexture(0,&m_mainFBO);
	m_finalPass->setTexture(1,&m_vblurFBO);
	m_finalPass->setTexture(2,&m_hblurFBO);

	setImageProperties(m_properties);
}

PostProcess::~PostProcess()
{
	delete m_hblurPass;
	delete m_vblurPass;
	delete m_raysPass;
	delete m_finalPass;
	delete m_hblurShader;
	delete m_vblurShader;
	delete m_raysShader;
	delete m_finalShader;
}

void PostProcess::widgetResized(int width, int height)
{
	m_viewportWidth = width;
	m_viewportHeight = height;
	m_mainFBO.release();
	m_mainFBO.init(width,height,GL_RGBA16F_ARB,false);
	m_hblurFBO.release();
	m_hblurFBO.init(width/2,height,GL_RGBA16F_ARB,false);
	m_vblurFBO.release();
	m_vblurFBO.init(width/2,height/2,GL_RGBA16F_ARB,false);

	m_finalShader->setUniform1f("windowWidth", width);
	m_finalShader->setUniform1f("windowHeight", height);

	m_hblurShader->setUniform1f("textureSize", width/2);
	m_vblurShader->setUniform1f("textureSize", height/2);
}

void PostProcess::setImageProperties(const slotsdata::ImageProperties &properties)
{
	m_properties = properties;

	m_hblurShader->setUniform1i("bloomSamples",m_properties.bloom().samples());
	m_hblurShader->setUniform1f("blurMean", m_properties.bloom().decay());
	m_vblurShader->setUniform1i("bloomSamples",m_properties.bloom().samples());
	m_vblurShader->setUniform1f("blurMean",m_properties.bloom().decay());
	m_finalShader->setUniform1f("exposure",m_properties.exposure());
	m_finalShader->setUniform1f("gamma",m_properties.gamma());
	m_finalShader->setUniform1f("contrast",m_properties.contrast());
	m_finalShader->setUniform1f("bloomAmount",m_properties.bloom().ammount());
}

void PostProcess::beginCapture()
{
    glActiveTexture(GL_TEXTURE10);
	m_mainFBO.beginCapture();
}

void PostProcess::endCapture()
{
	m_mainFBO.endCapture();
}

void PostProcess::doPostProcess()
{
	m_hblurPass->doPass(m_viewportWidth/2,m_viewportHeight);
	m_vblurPass->doPass(m_viewportWidth/2,m_viewportHeight/2);
	//m_raysPass->doPass(m_viewportWidth/2,m_viewportHeight);
	m_finalPass->doPass(m_viewportWidth,m_viewportHeight);
}

